package org.dicr.util.jds.gui;

import java.awt.*;
import java.io.*;

import javax.swing.*;

import org.dicr.event.*;
import org.dicr.gui.*;
import org.dicr.util.jds.*;

import com.borland.dx.dataset.*;

/***********************************************************************************************************************
 * @author Igor A Tarasov me@dicr.dn.ua
 * @version 021207
 **********************************************************************************************************************/
public class DataImageViewerPanel extends ImageViewerPanel implements ColumnAware {
	private static final long serialVersionUID = 1L;

	private DataSet dataset = null;

	private String columnName = null;

	private DataListener dataListener = new DataListener();

	/*******************************************************************************************************************
	 * Конструктор
	 ******************************************************************************************************************/
	public DataImageViewerPanel() {
		try {
			jbInit();
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		}
	}

	/*******************************************************************************************************************
	 * Инициализация
	 ******************************************************************************************************************/
	private void jbInit() {
	// NOP
	}

	/*******************************************************************************************************************
	 * Установка источника данных
	 ******************************************************************************************************************/
	@Override
    public void setDataSet(DataSet dataSet) {
		if (this.dataset != dataSet) try {
			if (this.dataset != null) {
				this.dataset.removeAccessListener(this.dataListener);
				this.dataset.removeNavigationListener(this.dataListener);
			}
			this.dataset = dataSet;
			if (this.dataset != null) {
				this.dataset.addAccessListener(this.dataListener);
				this.dataset.addNavigationListener(this.dataListener);
				this.dataset.open();
			}
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		} finally {
			try {
				updateImage();
			} catch (Exception ex) {
				DicrExceptionHandler.handleException(ex, this);
			}
		}
	}

	/*******************************************************************************************************************
	 * Возвращает источник данных
	 ******************************************************************************************************************/
	@Override
    public DataSet getDataSet() {
		return this.dataset;
	}

	/*******************************************************************************************************************
	 * Проверяет состояние источника
	 ******************************************************************************************************************/
	protected boolean isValidDataSetState() {
		return (this.dataset != null && this.dataset.isOpen() && this.columnName != null && this.dataset.hasColumn(this.columnName) != null);
	}

	/*******************************************************************************************************************
	 * Устанавливает имя колонки
	 ******************************************************************************************************************/
	@Override
    public void setColumnName(String theColumnName) {
		if (this.columnName != theColumnName) {
			this.columnName = theColumnName;
			updateImage();
		}
	}

	/*******************************************************************************************************************
	 * Возвращает имя колонки
	 ******************************************************************************************************************/
	@Override
    public String getColumnName() {
		return this.columnName;
	}

	/*******************************************************************************************************************
	 * Обновляет изображение
	 ******************************************************************************************************************/
	protected void updateImage() {
		this.setCursor(GuiMisc.CURSOR_WAIT);
		ImageIcon imicon = null;
		try {
			if (isValidDataSetState() && !this.dataset.isNull(this.columnName)) {
				InputStream in = this.dataset.getInputStream(this.columnName);
				if (in != null) {
					in.reset();
					if (in.available() > 0) imicon = this.imageIO.loadImage(in);
				}
			}
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		} finally {
			this.setCursor(GuiMisc.CURSOR_DEFAULT);
			super.setImage(imicon);
		}
	}

	/*******************************************************************************************************************
	 * Обновляет данные
	 ******************************************************************************************************************/
	protected void updateData() {
		this.setCursor(GuiMisc.CURSOR_WAIT);
		InputStream in = null;
		try {
			if (!isValidDataSetState()) return;
			Image image = getImage();
			if (image != null) {
				ByteArrayOutputStream ou = new ByteArrayOutputStream();
				this.imageIO.saveImage(ou, image);
				ou.flush();
				ou.close();
				byte[] buf = ou.toByteArray();
				in = new ByteArrayInputStream(buf);
				in.mark(buf.length);
			}
		} catch (Exception ex) {
			DicrExceptionHandler.handleException(ex, this);
		} finally {
			this.setCursor(GuiMisc.CURSOR_DEFAULT);
			this.dataset.setInputStream(this.columnName, in);
		}
	}

	/*******************************************************************************************************************
	 * Обновления состояния кнопок (переопределение)
	 ******************************************************************************************************************/
	@Override
	public void updateButtonState() {
		super.updateButtonState();
		if (this.loadButton.isEnabled() || this.clearButton.isEnabled()) {
			boolean theEditable = isValidDataSetState() && DataMisc.isDataSetEditable(this.dataset);
			if (theEditable) {
				Column col = this.dataset.hasColumn(this.columnName);
				theEditable = col.isEditable() && !col.isReadOnly();
			}
			if (this.loadButton.isEnabled() && !theEditable) this.loadButton.setEnabled(false);
			if (this.clearButton.isEnabled() && !theEditable) this.clearButton.setEnabled(false);
		}
	}

	/*******************************************************************************************************************
	 * Установка изображения (переопределение)
	 ******************************************************************************************************************/
	@Override
	public void setImage(ImageIcon image) {
		super.setImage(image);
		updateData();
	}

	/*******************************************************************************************************************
	 * ######################################################################### Слушатель данных
	 * #########################################################################
	 ******************************************************************************************************************/
	class DataListener implements AccessListener, NavigationListener {
		/***************************************************************************************************************
		 * Обработчик события навигации данных
		 **************************************************************************************************************/
		@Override
        public void navigated(NavigationEvent event) {
			try {
				updateImage();
			} catch (Exception ex) {
				DicrExceptionHandler.handleException(ex, this);
			}
		}

		/***************************************************************************************************************
		 * Обработка события доступа к данным
		 **************************************************************************************************************/
		@Override
        public void accessChange(AccessEvent e) {
			try {
				updateImage();
			} catch (Exception ex) {
				DicrExceptionHandler.handleException(ex, this);
			}
		}
	}
}
